使用 Angular 中的服务在组件之间发送数据 2
Sending data between components using a service in Angular 2
我正在尝试使用服务在两个组件之间发送数据。但是,当 'child' 组件首次加载时,我遇到了数据填充问题。
当您 select 从 release-list.component 上的无序列表中获取 'release' 时,它将通过路由器出口加载 release-detail.component。发布-detail.component 应该显示发布艺术家。
如果您 select 发布然后 select 第二次发布,它会起作用。但是在填充数据之前,我必须 'load' release-detail.component 两次。我觉得我很接近,但我一定错过了什么。任何帮助将不胜感激。
谢谢
我都提到了 and the Angular documentation
release.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { MockReleaseList, ReleaseInterface } from './mock-releases';
@Injectable()
export class ReleaseService {
private releaseSubject$ = new Subject();
getReleases(): ReleaseInterface[] {
return MockReleaseList;
}
getRelease() {
return this.releaseSubject$;
}
updateRelease(release: {artist: string, title: string, category: string}[]) {
// console.log(release);
this.releaseSubject$.next(release);
}
}
release-list.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { ReleaseService } from '../../../shared/services/release.service';
import { MockReleaseList, ReleaseInterface } from '../../../shared/services/mock-releases';
@Component({
selector: 'ostgut-releases',
template: `
<h3>Label List</h3>
<ul>
<li *ngFor="let release of releases" (click)="onSelect(release)">{{ release.artist }}</li>
</ul>
<router-outlet></router-outlet>
`,
})
export class ReleaseListComponent implements OnInit {
private releases: ReleaseInterface[];
constructor (
private _router: Router,
private _releaseService: ReleaseService
) {}
ngOnInit(): ReleaseInterface[] {
return this.releases = this._releaseService.getReleases();
}
onSelect(release: any): void {
this._releaseService.updateRelease(release);
this._router.navigate(['/release-list/release-detail', release.category]);
}
}
release-detail.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { ReleaseService } from '../../../../shared/services/release.service';
import { ReleaseInterface } from '../../../../shared/services/mock-releases';
@Component({
selector: 'ostgut-release-detail',
template: `
<h3>Release Detail</h3>
<p>{{ release.artist }}</p>
`,
})
export class ReleaseDetailComponent implements OnInit {
private routeParam: string;
private routeParamSub: any;
private release: any;
constructor(
private _activatedRoute: ActivatedRoute,
private _router: Router,
private _releaseService: ReleaseService
) {}
ngOnInit(): void {
this.release = this._releaseService.getRelease().subscribe(release=>{
return this.release = release;
});
}
}
我认为问题可能在于您的 Subject
在您在 ReleaseDetailComponent
中订阅它之前发布了它的值。当你第二次这样做时,一个新的 Release
被发布,并且 ReleaseDetailComponent
已经创建 - 这意味着它会起作用。
要解决此问题,您可以尝试在服务中使用 BehaviorSubject
而不是常规 Subject
。 BehaviorSubject
将为您提供最新发布的值,即使您在最后一个值发布后订阅它也是如此。它也需要一个默认值,所以你可能想在你的 ReleaseDetailComponent
模板中添加一些 null-checking。
实现可能如下所示:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; // <-- note the import!
import { MockReleaseList, ReleaseInterface } from './mock-releases';
@Injectable()
export class ReleaseService {
private releaseSubject$ = new BehaviorSubject(undefined);
// The rest is the same
}
并且在您的模板中,att null 检查,因为我们设置为 BehaviorSubject
的默认值是 undefined
。当然,您可以将默认值(传递给 BehaviorSubject
的构造函数的值)设置为空 Release
或您愿意的其他值。
template: `
<h3>Release Detail</h3>
<p>{{ release?.artist }}</p> <!-- Note the '?' -->
`,
如果您想了解有关不同类型 Subjects
的更多信息,请参阅以下文档:
希望对您有所帮助!
考虑使用 BehaviorSubject
作为代表。 订阅后 returns 主题的最后一个值,因此延迟加载的组件将始终使用最近的值更新:
@Injectable
export class ReleaseService {
releaseSource: BehaviorSubject = new BehaviorSubject(null);
// No difference when it comes to subscribing to the BehaviorSubject
}
BehaviorSubject
的基本示例:Angular 2 组件之间的交互
使用服务
我认为您在这里混淆了两个概念。有两种方法:
- 在 release-detail 组件中,您使用
@Input
声明 release
并从 release-list 传递它。您将把它作为组件中的变量供您使用。没有主题,没有订阅。
- 您使用上述服务,但您已经加载了详细信息。就像将它嵌入 release-list html 中一样,但是
*ngIf
设置为 false,不显示它。当您将所选版本放入您的主题时它会开始,然后您可以将 *ngIf
设置为 true,显示 release-detail 部分。
我正在尝试使用服务在两个组件之间发送数据。但是,当 'child' 组件首次加载时,我遇到了数据填充问题。
当您 select 从 release-list.component 上的无序列表中获取 'release' 时,它将通过路由器出口加载 release-detail.component。发布-detail.component 应该显示发布艺术家。
如果您 select 发布然后 select 第二次发布,它会起作用。但是在填充数据之前,我必须 'load' release-detail.component 两次。我觉得我很接近,但我一定错过了什么。任何帮助将不胜感激。
谢谢
我都提到了
release.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { MockReleaseList, ReleaseInterface } from './mock-releases';
@Injectable()
export class ReleaseService {
private releaseSubject$ = new Subject();
getReleases(): ReleaseInterface[] {
return MockReleaseList;
}
getRelease() {
return this.releaseSubject$;
}
updateRelease(release: {artist: string, title: string, category: string}[]) {
// console.log(release);
this.releaseSubject$.next(release);
}
}
release-list.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { ReleaseService } from '../../../shared/services/release.service';
import { MockReleaseList, ReleaseInterface } from '../../../shared/services/mock-releases';
@Component({
selector: 'ostgut-releases',
template: `
<h3>Label List</h3>
<ul>
<li *ngFor="let release of releases" (click)="onSelect(release)">{{ release.artist }}</li>
</ul>
<router-outlet></router-outlet>
`,
})
export class ReleaseListComponent implements OnInit {
private releases: ReleaseInterface[];
constructor (
private _router: Router,
private _releaseService: ReleaseService
) {}
ngOnInit(): ReleaseInterface[] {
return this.releases = this._releaseService.getReleases();
}
onSelect(release: any): void {
this._releaseService.updateRelease(release);
this._router.navigate(['/release-list/release-detail', release.category]);
}
}
release-detail.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { ReleaseService } from '../../../../shared/services/release.service';
import { ReleaseInterface } from '../../../../shared/services/mock-releases';
@Component({
selector: 'ostgut-release-detail',
template: `
<h3>Release Detail</h3>
<p>{{ release.artist }}</p>
`,
})
export class ReleaseDetailComponent implements OnInit {
private routeParam: string;
private routeParamSub: any;
private release: any;
constructor(
private _activatedRoute: ActivatedRoute,
private _router: Router,
private _releaseService: ReleaseService
) {}
ngOnInit(): void {
this.release = this._releaseService.getRelease().subscribe(release=>{
return this.release = release;
});
}
}
我认为问题可能在于您的 Subject
在您在 ReleaseDetailComponent
中订阅它之前发布了它的值。当你第二次这样做时,一个新的 Release
被发布,并且 ReleaseDetailComponent
已经创建 - 这意味着它会起作用。
要解决此问题,您可以尝试在服务中使用 BehaviorSubject
而不是常规 Subject
。 BehaviorSubject
将为您提供最新发布的值,即使您在最后一个值发布后订阅它也是如此。它也需要一个默认值,所以你可能想在你的 ReleaseDetailComponent
模板中添加一些 null-checking。
实现可能如下所示:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; // <-- note the import!
import { MockReleaseList, ReleaseInterface } from './mock-releases';
@Injectable()
export class ReleaseService {
private releaseSubject$ = new BehaviorSubject(undefined);
// The rest is the same
}
并且在您的模板中,att null 检查,因为我们设置为 BehaviorSubject
的默认值是 undefined
。当然,您可以将默认值(传递给 BehaviorSubject
的构造函数的值)设置为空 Release
或您愿意的其他值。
template: `
<h3>Release Detail</h3>
<p>{{ release?.artist }}</p> <!-- Note the '?' -->
`,
如果您想了解有关不同类型 Subjects
的更多信息,请参阅以下文档:
希望对您有所帮助!
考虑使用 BehaviorSubject
作为代表。
@Injectable
export class ReleaseService {
releaseSource: BehaviorSubject = new BehaviorSubject(null);
// No difference when it comes to subscribing to the BehaviorSubject
}
BehaviorSubject
的基本示例:Angular 2 组件之间的交互
使用服务
我认为您在这里混淆了两个概念。有两种方法:
- 在 release-detail 组件中,您使用
@Input
声明release
并从 release-list 传递它。您将把它作为组件中的变量供您使用。没有主题,没有订阅。 - 您使用上述服务,但您已经加载了详细信息。就像将它嵌入 release-list html 中一样,但是
*ngIf
设置为 false,不显示它。当您将所选版本放入您的主题时它会开始,然后您可以将*ngIf
设置为 true,显示 release-detail 部分。